home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / prospero / propsero.lha / prospero-beta.4.2e / user / als.c < prev    next >
C/C++ Source or Header  |  1992-02-09  |  10KB  |  506 lines

  1. /*
  2. **    A simple fast ls(1) replacement for Prospero. Only supports
  3. **    a small subset of the multitude of ls options.
  4. **
  5. **    A quick whip-up for the Prospero FTPD.
  6. **
  7. **    Steve Cliffe
  8. **    Department of Computer Science
  9. **    University of Wollongong
  10. **    Australia
  11. **
  12. **    steve@cs.uow.edu.au
  13. **
  14. **    January 1992
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <sys/param.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <string.h>
  22. #include <search.h>
  23.  
  24. #include <pfs.h>
  25. #include <pcompat.h>
  26. #include <perrno.h>
  27.  
  28. #define TABSIZE        500        /* Max number of subdirs */
  29.  
  30. #define    DAYSPERNYEAR    (365)
  31. #define    SECSPERDAY    (60*60*24)
  32.  
  33. int        perrno;
  34. int        pfs_debug = 0;
  35.     
  36. extern int    optind;    
  37.  
  38. int        opt_long = 0;        /* Listing options */
  39. int        opt_revsort = 0;
  40. int        opt_timesort = 0;
  41. int        opt_recursive = 0;
  42. int        opt_prospero = 0;
  43. int        opt_union = 0;
  44.  
  45. char        *progname;
  46.  
  47. struct my_stat {            /* Info about a file */
  48.     unsigned    st_size;
  49.     unsigned    st_blocks;
  50.     long        st_links;
  51.     mode_t        st_mode;
  52.     time_t        st_mtime;
  53.     char        st_owner[12];
  54.     char        st_group[12];
  55.     char        st_modes[12];
  56. };
  57.  
  58. struct tabent {
  59.     char        name[128];    /* Link name */
  60.     char        host[128];    /* Link's host */
  61.     char        filename[128];    /* Link's system level filename */
  62.     long        magic_no;    /* Link's magic number */
  63. };
  64.  
  65. struct tabent    table[TABSIZE];        /* Cycle detection table */
  66. unsigned int    table_entries = 0;
  67. unsigned int    table_width = sizeof(struct tabent);
  68.  
  69. main(argc,argv)
  70.    int        argc;
  71.    char        *argv[];
  72. {
  73.     int        opt;
  74.  
  75.     progname = argv[0];
  76.     
  77.     while ((opt = getopt(argc, argv, "lgrtRPU")) != EOF) {
  78.         switch (opt) {
  79.  
  80.         case 'l':
  81.             opt_long = 1;
  82.             break;
  83.         case 'r':
  84.             opt_revsort = 1;
  85.             break;
  86.         case 't':
  87.             opt_timesort = 1;
  88.             break;
  89.         case 'R':
  90.             opt_recursive++;
  91.             break;
  92.  
  93.         case 'P':
  94.             opt_prospero = 1;
  95.             break;
  96.  
  97.         case 'U':
  98.             opt_union = 1;
  99.             break;
  100.             
  101.         default:
  102.             fprintf(stderr,
  103.             "Usage: %0 [-lrtR] [file or directory name]\n", progname);
  104.             exit(1);
  105.         }
  106.     }
  107.  
  108.     argc -= optind;
  109.     argv += optind;
  110.  
  111.     list_directory(argc ? *argv : "");
  112.     
  113.     exit(0);
  114. }
  115.  
  116. /*
  117. ** list_directory:
  118. **
  119. **    List out a directory. (i.e. do all the work)
  120. */
  121.  
  122. list_directory(path)
  123.    char *path;
  124. {
  125.     VDIR_ST        dir_st;
  126.     VDIR        dir= &dir_st;
  127.     VLINK        l;
  128.     int        flags = GVD_LREMEXP;
  129.     int        error, been_here, old_table_size;
  130.     char        newpath[MAXPATHLEN];
  131.     struct tabent    newent;
  132.     int        compare();
  133.  
  134.     vdir_init(dir);
  135.  
  136.     if (opt_union)
  137.         flags = GVD_UNION;
  138.     if (opt_long)
  139.         flags |= GVD_ATTRIB;
  140.         
  141.     error = rd_vdir(path, 0, dir, flags);
  142.  
  143.     if(error && (error != DIRSRV_NOT_DIRECTORY)) {
  144.         fprintf(stderr, "%s", progname);
  145.         perrmesg(" failed: ", error, NULL);
  146.         exit(1);
  147.     }
  148.  
  149.     if(pwarn)
  150.         pwarnmesg("WARNING: ", 0, NULL);
  151.  
  152.  
  153.     /*
  154.     **    Display this directory.
  155.     */
  156.  
  157.     l = dir->links;
  158.  
  159.     while(l) {
  160.         display_link(l);
  161.         l = l->next;
  162.     }
  163.  
  164.     /*
  165.     **    Handle union links.
  166.     */
  167.     
  168.     l = dir->ulinks;    
  169.  
  170.     if ((error != DIRSRV_NOT_DIRECTORY))
  171.         while(l) {
  172.         if ((l->expanded == FALSE) || (l->expanded == FAILED)) 
  173.             display_link(l);
  174.         
  175.         l = l->next;
  176.         }
  177.         
  178.     /*
  179.     **    Display subdirectories if requested (-R).
  180.     */
  181.     
  182.     if (opt_recursive) {
  183.         l = dir->links;
  184.         while (l) {
  185.  
  186.             /*
  187.             **    Make sure we haven't been here before.
  188.             */
  189.  
  190.  
  191.             strcpy(newent.name, l->name);
  192.             strcpy(newent.host, l->host);
  193.             strcpy(newent.filename, l->filename);
  194.             newent.magic_no = l->f_magic_no;
  195.     
  196.             if (table_entries == TABSIZE) {
  197.                 fprintf(stderr, "%s: cycle detection table overflow\n", progname);
  198.                 exit(1);
  199.                 }
  200.  
  201.             old_table_size = table_entries;
  202.             been_here = 0;
  203.  
  204.             /*
  205.             **    Don't cross machine boundaries
  206.             **    unless -R option is specified twice.
  207.             */
  208.             
  209.             if (strcmp(table[table_entries].host, l->host) &&
  210.                 (opt_recursive != 2))
  211.                 goto next;
  212.  
  213.             /*
  214.             **    Make sure we haven't been here before.
  215.             */
  216.             
  217.             lsearch((char *) &newent, (char *) &table[0], &table_entries,
  218.                     table_width, compare);
  219.  
  220.             if (old_table_size == table_entries)    
  221.                 been_here = 1;
  222.  
  223.             if ((strcmp(l->type, "DIRECTORY") == 0) && (!been_here)) {
  224.                 if (path[0] == '\0')
  225.                     strcpy(newpath, l->name);
  226.                 else
  227.                     sprintf(newpath, "%s/%s", path, l->name);
  228.                 printf("\n%s:\n", newpath);
  229.                 list_directory(newpath);
  230.             }
  231. next:
  232.             l = l->next;
  233.         }
  234.     }
  235.  
  236.     vllfree(dir->links);
  237.     return;
  238. }
  239.  
  240. /*
  241. ** display_link:
  242. **
  243. **    Display a link based on what options have been selected.
  244. */
  245.  
  246. display_link(l)
  247.    VLINK l;
  248. {   
  249.     if (opt_long) {
  250.         if (opt_prospero)
  251.             display_prospero_long(l);
  252.         else
  253.             display_long(l);
  254.         return;
  255.     }
  256.     
  257.     if (opt_prospero)
  258.         printf("%c%c %-20.20s %c%-15.15s %-38.38s\n",
  259.              ((l->linktype == 'L') ? ' ' : l->linktype),
  260.          (l->expanded ? 'F' : ' '),
  261.          l->name,
  262.          (l->filters ? '*' : ' '),
  263.          l->host,l->filename);
  264.     else
  265.         printf("%s\n", l->name);
  266. }
  267.  
  268. /*
  269. ** display_long:
  270. **
  271. **    Print out a directory tabent in the UNIX ls -l format. Code to
  272. **    fill in the stat(2) buffer based on lib/pcompat/stat.c
  273. */
  274.  
  275. display_long(l)
  276.    VLINK l;
  277. {
  278.     PATTRIB        ap, apnext;
  279.     struct my_stat    stat_buffer;
  280.     struct my_stat    *sbp = &stat_buffer;
  281.     char        mode_string[15];
  282.     int        size;
  283.  
  284.     sbp->st_size = 0;
  285.     sbp->st_mtime = (time_t) 0;
  286.     strcpy(sbp->st_owner, "-");
  287.     strcpy(sbp->st_group, "-");
  288.     sbp->st_mode = 0;
  289.     sbp->st_modes[0] = '\0';
  290.  
  291.     if (strcmp(l->type, "DIRECTORY") == 0)
  292.         sbp->st_mode |= (S_IFDIR | 0555);
  293.     else
  294.         sbp->st_mode |= 0444;
  295.         
  296.     sbp->st_links = 1;
  297.  
  298.     ap = NULL;
  299.  
  300.     if (l->lattrib == NULL)
  301.         ap = pget_at(l, "ALL");
  302.  
  303.     if ((ap == NULL) && (l->lattrib)) {
  304.         ap = l->lattrib;
  305.         l->lattrib = NULL;
  306.     }
  307.  
  308.     while (ap) {
  309.         if ((strcmp(ap->aname, "SIZE") == 0) &&
  310.             (strcmp(ap->avtype, "ASCII") == 0)) {
  311.             sscanf(ap->value.ascii, "%d", &size);
  312.             sbp->st_size = size;
  313.             sbp->st_blocks = (size + 511) / 512;
  314.         }
  315.         if ((strcmp(ap->aname, "NATIVE-OWNER") == 0) &&
  316.             (strcmp(ap->avtype, "ASCII") == 0))
  317.             strcpy(sbp->st_owner, ap->value.ascii);
  318.         if ((strcmp(ap->aname, "NATIVE-GROUP") == 0) &&
  319.             (strcmp(ap->avtype, "ASCII") == 0))
  320.             strcpy(sbp->st_group, ap->value.ascii);
  321.         if ((strcmp(ap->aname, "UNIX-MODES") == 0) &&
  322.             (strcmp(ap->avtype, "ASCII") == 0))
  323.             strcpy(sbp->st_modes, ap->value.ascii);
  324.         if ((strcmp(ap->aname, "LAST-MODIFIED") == 0) &&
  325.             (strcmp(ap->avtype, "ASCII") == 0))
  326.             sbp->st_mtime = asntotime(ap->value.ascii);
  327.  
  328.         apnext = ap->next;
  329.         atfree(ap);
  330.         ap = apnext;
  331.     }
  332.  
  333.     /*
  334.     **    Now display the tabent.
  335.     */
  336.  
  337.     if (sbp->st_modes[0] == '\0')
  338.         (void) strmode(sbp->st_mode, mode_string);
  339.     else
  340.         strcpy(mode_string, sbp->st_modes);
  341.  
  342.     printf("%s %3u %-8s %-8s %8u ", mode_string, sbp->st_links,
  343.            sbp->st_owner, sbp->st_group, sbp->st_size);
  344.  
  345.     printtime(sbp->st_mtime);
  346.  
  347.     printf("%s\n", l->name);
  348. }
  349.  
  350. /*
  351. ** display_prospero_long:
  352. **
  353. **    Print out verbose information about a link. Taken from vls.c
  354. */
  355.  
  356. display_prospero_long(l)
  357.    VLINK l;
  358. {
  359.     VLINK        fil;
  360.     PATTRIB        ap;
  361.  
  362.     printf("\n      Name: %s\n",l->name);
  363.         printf("   ObjType: %s\n",l->type);
  364.     printf("  LinkType: %s\n",((l->linktype == 'U') ? "Union" : "Standard"));
  365.     printf("  HostType: %s\n",l->hosttype);
  366.     printf("      Host: %s\n",l->host);
  367.     printf("  NameType: %s\n",l->nametype);
  368.     printf("  Pathname: %s\n",l->filename);
  369.  
  370.     if(l->version)
  371.         printf("   Version: %d\n",l->version);
  372.         if(l->f_magic_no)
  373.         printf("     Magic: %d\n",l->f_magic_no);
  374.  
  375.     if (opt_long) {        /* Show attributes and filters */
  376.  
  377.         ap = NULL;
  378.  
  379.         if (l->lattrib == NULL)
  380.             ap = pget_at(l, "ALL");
  381.  
  382.         if ((ap == NULL) && (l->lattrib)) {
  383.             ap = l->lattrib;
  384.             l->lattrib = NULL;
  385.         }
  386.  
  387.         printf("Attributes:\n\n");
  388.         while(ap) {
  389.             printf("%15s: ",ap->aname);
  390.             if (strcmp(ap->avtype,"ASCII") == 0)
  391.                 printf("%s\n",ap->value.ascii);
  392.             else if (strcmp(ap->avtype,"LINK") == 0)
  393.                 printf("%s %s %s %d %d\n",
  394.                        ap->value.link->name,ap->value.link->host,
  395.                        ap->value.link->filename,
  396.                        ap->value.link->version,
  397.                        ap->value.link->f_magic_no);
  398.             else
  399.                 printf("<unknown-type %s>\n",ap->avtype);
  400.             
  401.             ap = ap->next;
  402.             }
  403.         
  404.         printf("\n");
  405.         atlfree(ap);
  406.  
  407.         if(l->filters) {
  408.             printf("   Filters: \n");
  409.             fil = l->filters;
  410.             while(fil) {
  411.                 printf("\n      HostType: %s\n",fil->hosttype);
  412.                 printf("          Host: %s\n",fil->host);
  413.                 printf("      NameType: %s\n",fil->nametype);
  414.                 printf("      Pathname: %s\n",fil->filename);
  415.                 if (fil->f_magic_no)
  416.                     printf("         Magic: %d\n",fil->f_magic_no);
  417.                 if (fil->args)
  418.                     printf("          Args: %s\n",fil->args);
  419.                 fil = fil->next;
  420.             }
  421.         }
  422.         printf("\n");
  423.     }
  424. }
  425.  
  426. /*
  427. **    compare - Compare 2 nodes to detect a cycle.
  428. */
  429.  
  430. compare(one, two)
  431.    struct tabent    *one, *two;
  432. {
  433.     if (strcmp(one->name, two->name))
  434.         return(1);
  435.     if (strcmp(one->host, two->host))
  436.         return(1);
  437.     if (strcmp(one->filename, two->filename))
  438.         return(1);
  439.     if ((one->magic_no == 0) || (two->magic_no == 0) ||
  440.         (one->magic_no == two->magic_no))
  441.         return(0);
  442.     else
  443.         return(1);
  444. }
  445.  
  446.  
  447. /*    ----------------------------------------------------------    */
  448.  
  449. /*
  450. **    strmode - Pinched from BSD ls. 
  451. */
  452.  
  453. strmode(mode,modestr)
  454.    short    mode;
  455.    char        *modestr;
  456. {
  457.  
  458.     strcpy(modestr,"----------");
  459.  
  460.     if(mode & S_IFDIR) modestr[0] = 'd';
  461.     if((mode & S_IFLNK) == S_IFLNK) modestr[0] = 'l';
  462.     if(mode & S_IREAD) modestr[1] = 'r';
  463.     if(mode & S_IWRITE) modestr[2] = 'w';
  464.     if(mode & S_IEXEC) modestr[3] = 'x';
  465.     if(mode & S_ISUID) modestr[3] = 's';
  466.     if(mode & (S_IREAD>>3)) modestr[4] = 'r';
  467.     if(mode & (S_IWRITE>>3)) modestr[5] = 'w';
  468.     if(mode & (S_IEXEC>>3)) modestr[6] = 'x';
  469.     if(mode & S_ISGID) modestr[6] = 's';
  470.     if(mode & (S_IREAD>>6)) modestr[7] = 'r';
  471.     if(mode & (S_IWRITE>>6)) modestr[8] = 'w';
  472.     if(mode & (S_IEXEC>>6)) modestr[9] = 'x';
  473. }
  474.  
  475. /*
  476. **    printtime - pinched from the BSD ls.
  477. */
  478.  
  479. printtime(ftime)
  480.    time_t ftime;
  481. {
  482.     int i;
  483.     char *longstring, *ctime();
  484.     time_t time();
  485.  
  486.     if(ftime == 0) fputs("-            ",stdout);
  487.     else {
  488.  
  489.         DISABLE_PFS(longstring = ctime((long *)&ftime));
  490.         for (i = 4; i < 11; ++i)
  491.         (void)putchar(longstring[i]);
  492.  
  493. #define    SIXMONTHS    ((DAYSPERNYEAR / 2) * SECSPERDAY)
  494.         if (ftime + SIXMONTHS > time((time_t *)NULL))
  495.         for (i = 11; i < 16; ++i)
  496.             (void)putchar(longstring[i]);
  497.         else {
  498.         (void)putchar(' ');
  499.         for (i = 20; i < 24; ++i)
  500.             (void)putchar(longstring[i]);
  501.         }
  502.         (void)putchar(' ');
  503.     }
  504. }
  505.  
  506.